﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Collections.ObjectModel;

namespace PatriotCreations.JpegData
{
    public abstract class ImageReader : IDisposable
    {   
        /// <summary>
        /// Constructor that Takes an ImageSource
        /// </summary>
        /// <param name="imageSource">A valid stream that represents a jpeg image.</param>
        public ImageReader(Stream imageSource)
        {
            // If no data in the image source, nothing can be done with it.
            if (imageSource.Length == 0)
                throw new InvalidDataException("Image stream is empty.");

            this.ImageSource = imageSource;

            Initialize();
        }

        /// <summary>
        /// Initialize the image source.
        /// </summary>
        protected void Initialize()
        {
            this.Decoder = new JpegBitmapDecoder(this.ImageSource,
                                                 BitmapCreateOptions.PreservePixelFormat,
                                                 BitmapCacheOption.Default);

            this.Source = this.Decoder.Frames[0];
            this.Meta = (BitmapMetadata)this.Source.Metadata;

            // Get info about the file not available elsewhere
            FileStream file = (FileStream)this.ImageSource;
            this.Name = file.Name;
        }

        protected Stream ImageSource { get; set; }
        protected JpegBitmapDecoder Decoder { get; set; }
        protected BitmapSource Source { get; set; }
        protected BitmapMetadata Meta { get; set; }

        public string Name { get; set; }

        #region Mapped to BitmapMetadata

        public string ApplicationName
        {
            get { return this.Meta.ApplicationName; }
        }

        public System.Collections.ObjectModel.ReadOnlyCollection<string> Author
        {
            get { return this.Meta.Author; }
        }

        public string CameraManufacturer
        {
            get { return this.Meta.CameraManufacturer; }
        }

        public string CameraModel
        {
            get { return this.Meta.CameraModel; }
        }

        public string Comment
        {
            get { return this.Meta.Comment; }
        }

        public string Copyright
        {
            get { return this.Meta.Copyright; }
        }

        public DateTime DateTaken
        {
            get { return Convert.ToDateTime(this.Meta.DateTaken); }
        }

        public string Format
        {
            get { return this.Meta.Format; }
        }

        public System.Collections.ObjectModel.ReadOnlyCollection<string> Keywords
        {
            get { return this.Meta.Keywords; }
        }

        public string Location
        {
            get { return this.Meta.Location; }
        }

        public int Rating
        {
            get { return this.Meta.Rating; }
        }

        public string Subject
        {
            get { return this.Meta.Subject; }
        }

        public string Title
        {
            get { return this.Meta.Title; }
        }

        #endregion

        #region Common Accross Formats

        public virtual string City { get; set; }
        public virtual string State { get; set; }
        public virtual string Country { get; set; }
        public virtual string Category { get; set; }
        public virtual string[] SubCategories { get; set; }
        public virtual string AuthorsPosition { get; set; }
        public virtual string Credit { get; set; }
        public virtual string Urgency { get; set; }
        public virtual string DateCreated { get; set; }
        public virtual string ImageLocation { get; set; }
        public virtual string Creator { get; set; }
        public virtual string CopyrightNotice { get; set; }

        #endregion

        public void Dispose()
        {
            // Make sure that the image source is released here.
            if (this.ImageSource != null)
                this.ImageSource.Dispose();

            GC.SuppressFinalize(this);
        }
    }
}
